#include "Graphics.h"
#include "Game.h"
#include <sstream>

int Graphics::Initialize(HWND &hWnd) {

	DXGI_SWAP_CHAIN_DESC scd;

	SecureZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

	DEVMODE lpDevMode;

	SecureZeroMemory(&lpDevMode, sizeof(DEVMODE));
	lpDevMode.dmSize = sizeof(DEVMODE);

	scd.BufferCount = 1;									// one back buffer
	scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;		// use 32-bit color
	scd.BufferDesc.Width = (windowSize.right - windowSize.left);
	scd.BufferDesc.Height = (windowSize.bottom - windowSize.top);
	if(FAILED(EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &lpDevMode))) scd.BufferDesc.RefreshRate.Numerator = 60;
	else scd.BufferDesc.RefreshRate.Numerator = lpDevMode.dmDisplayFrequency;
	scd.BufferDesc.RefreshRate.Denominator = 1;
	scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;		// how swap chain is to be used
	scd.OutputWindow = hWnd;								// the window to be used
	scd.SampleDesc.Count = 4;								// how many multisamples
	scd.SampleDesc.Quality = 0;								// multisample quality level
	scd.Windowed = TRUE;									// windowed/full-screen mode
	scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;		// allow full-screen switching;

	if(FAILED(D3D11CreateDeviceAndSwapChain(
		NULL,
		D3D_DRIVER_TYPE_HARDWARE,
		NULL,
		NULL,
		NULL,
		NULL,
		D3D11_SDK_VERSION,
		&scd,
		&this->swapchain,
		&this->dev,
		NULL,
		&this->devcon))) return E_GRAPHICS_INIT_FAILED;

	D3D11_TEXTURE2D_DESC texd;
	SecureZeroMemory(&texd, sizeof(texd));

	texd.Width = windowSize.right - windowSize.left;
	texd.Height = windowSize.bottom - windowSize.top;
	texd.ArraySize = 1;
	texd.MipLevels = 1;
	texd.SampleDesc.Count = 4;
	texd.Format = DXGI_FORMAT_D32_FLOAT;
	texd.BindFlags = D3D11_BIND_DEPTH_STENCIL;

	ID3D11Texture2D* pDepthBuffer;
	if(FAILED(this->dev->CreateTexture2D(&texd, NULL, &pDepthBuffer))) return E_GRAPHICS_INIT_FAILED;

	D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
	SecureZeroMemory(&dsvd, sizeof(dsvd));

	dsvd.Format = DXGI_FORMAT_D32_FLOAT;
	dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;

	if(FAILED(this->dev->CreateDepthStencilView(pDepthBuffer, &dsvd, &this->zbuffer))) return E_GRAPHICS_INIT_FAILED;
	pDepthBuffer->Release();

	// get the address of the back buffer
	ID3D11Texture2D *pBackBuffer;
	this->swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

	// use the back buffer address to create the render target
	if(FAILED(this->dev->CreateRenderTargetView(pBackBuffer, NULL, &this->backbuffer))) return E_GRAPHICS_INIT_FAILED;
	pBackBuffer->Release();

	// set the viewport
	D3D11_VIEWPORT viewport;
	SecureZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

	viewport.TopLeftX = 0;
	viewport.TopLeftY = 0;
	viewport.Width = (windowSize.right - windowSize.left);
	viewport.Height = (windowSize.bottom - windowSize.top);
	viewport.MinDepth = 0;
	viewport.MaxDepth = 1;

	this->devcon->RSSetViewports(1, &viewport);

	if(this->InitPipeline()) {
		Logger::Log(E_PIPELINE_INIT_FAILED, "Error initializing rendering pipeline!", __FILE__, __LINE__, LOG_ERROR);
		return E_PIPELINE_INIT_FAILED;
	}

	D3D11_BUFFER_DESC bd;
	SecureZeroMemory(&bd, sizeof(bd));

	bd.Usage = D3D11_USAGE_DYNAMIC;
	bd.ByteWidth = sizeof(VERTEX) * 4;
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;

	this->dev->CreateBuffer(&bd, NULL, &this->pVBuffer);

	// Create blend state

	D3D11_BLEND_DESC BSDesc;

	BSDesc.IndependentBlendEnable = false;
	BSDesc.AlphaToCoverageEnable = true;

	BSDesc.RenderTarget[0].BlendEnable = true;
	BSDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
	BSDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
	BSDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;

	BSDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
	BSDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
	BSDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;

	BSDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

	this->dev->CreateBlendState(&BSDesc, &this->blendstate);

	this->LoadCharacterTexture("error.png");
	this->LoadMenuTexture("placeholder.png");

	Logger::Log("Graphics Module successfully initialized", __FILE__, __LINE__);
	return 0;
}

int Graphics::Shutdown() {

	Logger::Log("Shutting Down Graphics Module...", __FILE__, __LINE__);

	this->swapchain->SetFullscreenState(FALSE, NULL);

	for(int i = (this->CharacterTextures.size() - 1); i >=  0; i--) {
		this->CharacterTextures[i].pTexture->Release();
		this->CharacterTextures.pop_back();
	}

	for(int i = (this->MenuTextures.size() - 1); i >= 0; i--) {
		this->MenuTextures[i].pTexture->Release();
		this->MenuTextures.pop_back();
	}

	this->swapchain->Release();
	this->dev->Release();
	this->devcon->Release();
	this->backbuffer->Release();
	this->pPS->Release();
	this->pVS->Release();
	this->pVSMenu->Release();
	this->pCBuffer->Release();
	this->pVBuffer->Release();
	this->pLayout->Release();
	this->zbuffer->Release();
	this->blendstate->Release();

	return 0;
}

void Graphics::RenderFrame() {

	static int frames = 0;
	static int t = time(0);

	if((time(0) - t) >= 1) {
		this->fps = frames;
		frames = 0;
		t = time(0);
	}

	if(Game::InputPtr->ToggledKeys.F12) this->swapchain->SetFullscreenState(TRUE, NULL);
	else this->swapchain->SetFullscreenState(FALSE, NULL);

	// clear the back buffer to a deep blue
	this->devcon->ClearRenderTargetView(this->backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));

	this->devcon->ClearDepthStencilView(this->zbuffer, D3D11_CLEAR_DEPTH, 1.0f, 0.0f);

	// render all Characters

	Graphics::RenderCharacters();

	Graphics::RenderMapTiles();

	Graphics::RenderMenu();

	Graphics::RenderCursor();

	// switch the back buffer and the front buffer
	this->swapchain->Present(0, 0);

	frames++;

	char buffer[20];

	itoa(this->fps, buffer, 10);

	SetWindowTextA(Game::window, buffer);

}

void Graphics::RenderMapTiles() {

	this->devcon->OMSetRenderTargets(1, &this->backbuffer, this->zbuffer);

	this->devcon->VSSetShader(this->pVS, 0, 0);
	this->devcon->PSSetShader(this->pPS, 0, 0);

	UINT stride = sizeof(VERTEX);
	UINT offset = 0;
	this->devcon->IASetVertexBuffers(0, 1, &this->pVBuffer, &stride, &offset);

	this->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

	this->devcon->OMSetBlendState(this->blendstate, NULL, 0xffffffff);

	D3D11_MAPPED_SUBRESOURCE ms;

	for(unsigned int i = 0; i < Game::MapTilePtrs.size(); i++) {
		if(Game::MapTilePtrs[i] != NULL) {
			this->devcon->Map(this->pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
			memcpy(ms.pData, Game::MapTilePtrs[i]->Quad, sizeof(Game::MapTilePtrs[i]->Quad));
			this->devcon->Unmap(this->pVBuffer, NULL);
				
			D3DXMATRIX matRotate, matTranslate, matView, matProjection, matFinal;

			static float Time = 0.0f; Time += 0.00010f;

			// create a view matrix
			D3DXMatrixLookAtRH(&matView,
							   &D3DXVECTOR3(Game::CameraPtr->x, Game::CameraPtr->y, Game::CameraPtr->z),    // the camera position
							   &D3DXVECTOR3(Game::CameraPtr->lookatX, Game::CameraPtr->lookatY, Game::CameraPtr->lookatZ),    // the look-at position
						       &D3DXVECTOR3(0.0f, 1.0f, 0.0f));   // the up direction

			// create a projection matrix
			D3DXMatrixPerspectiveFovRH(&matProjection,
				                       (FLOAT)D3DXToRadian(45),                    // field of view
									   (FLOAT)(windowSize.right - windowSize.left) / (FLOAT)(windowSize.bottom - windowSize.top), // aspect ratio
						               1.0f,                                       // near view-plane
							           100.0f);                                    // far view-plane
	
			//D3DXMatrixRotationYawPitchRoll(&matRotate, Game::MapTilePtrs[i]->GetYaw(), Game::MapTilePtrs[i]->GetPitch(), Game::MapTilePtrs[i]->GetRoll());
	
			D3DXMatrixTranslation(&matTranslate, Game::MapTilePtrs[i]->xPos, Game::MapTilePtrs[i]->yPos, 0.0f);
	
			// create the final transform
			matFinal = /*matRotate **/ matTranslate * matView * matProjection;
	
			this->devcon->UpdateSubresource(this->pCBuffer, 0, 0, &matFinal, 0, 0);
			if(this->MapTileTextures[Game::MapTilePtrs[i]->textureID].pTexture != NULL) this->devcon->PSSetShaderResources(0, 1, &this->MapTileTextures[Game::MapTilePtrs[i]->textureID].pTexture);
	
			this->devcon->Draw(4, 0);
		}

	}

}

void Graphics::RenderCharacters() {

	this->devcon->OMSetRenderTargets(1, &this->backbuffer, this->zbuffer);

	this->devcon->VSSetShader(this->pVS, 0, 0);
	this->devcon->PSSetShader(this->pPS, 0, 0);

	UINT stride = sizeof(VERTEX);
	UINT offset = 0;
	this->devcon->IASetVertexBuffers(0, 1, &this->pVBuffer, &stride, &offset);

	this->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

	this->devcon->OMSetBlendState(this->blendstate, NULL, 0xffffffff);

	D3D11_MAPPED_SUBRESOURCE ms;

	for(unsigned int i = 0; i < Game::CharactersPtrs.size(); i++) {
		if(Game::CharactersPtrs[i] != NULL) {
			this->devcon->Map(this->pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
			memcpy(ms.pData, Game::CharactersPtrs[i]->CharacterQuad, sizeof(Game::CharactersPtrs[i]->CharacterQuad));
			this->devcon->Unmap(this->pVBuffer, NULL);
				
			D3DXMATRIX matRotate, matTranslate, matView, matProjection, matFinal;

			static float Time = 0.0f; Time += 0.00010f;

			// create a view matrix
			D3DXMatrixLookAtRH(&matView,
							   &D3DXVECTOR3(Game::CameraPtr->x, Game::CameraPtr->y, Game::CameraPtr->z),    // the camera position
							   &D3DXVECTOR3(Game::CameraPtr->lookatX, Game::CameraPtr->lookatY, Game::CameraPtr->lookatZ),    // the look-at position
						       &D3DXVECTOR3(0.0f, 1.0f, 0.0f));   // the up direction

			// create a projection matrix
			D3DXMatrixPerspectiveFovRH(&matProjection,
				                       (FLOAT)D3DXToRadian(45),                    // field of view
									   (FLOAT)(windowSize.right - windowSize.left) / (FLOAT)(windowSize.bottom - windowSize.top), // aspect ratio
						               1.0f,                                       // near view-plane
							           100.0f);                                    // far view-plane
	
			D3DXMatrixRotationYawPitchRoll(&matRotate, Game::CharactersPtrs[i]->GetYaw(), Game::CharactersPtrs[i]->GetPitch(), Game::CharactersPtrs[i]->GetRoll());
	
			D3DXMatrixTranslation(&matTranslate, Game::CharactersPtrs[i]->GetCX(), Game::CharactersPtrs[i]->GetCY(), 0.0f);
	
			// create the final transform
			matFinal = matRotate * matTranslate * matView * matProjection;
	
			this->devcon->UpdateSubresource(this->pCBuffer, 0, 0, &matFinal, 0, 0);
			if(this->CharacterTextures[Game::CharactersPtrs[i]->texUID].pTexture != NULL) this->devcon->PSSetShaderResources(0, 1, &this->CharacterTextures[Game::CharactersPtrs[i]->texUID].pTexture);
	
			this->devcon->Draw(4, 0);
		}

	}

}

void Graphics::RenderMenu() {

	this->devcon->OMSetRenderTargets(1, &this->backbuffer, NULL);

	this->devcon->VSSetShader(this->pVSMenu, 0, 0);

	UINT stride = sizeof(VERTEX);
	UINT offset = 0;
	this->devcon->IASetVertexBuffers(0, 1, &this->pVBuffer, &stride, &offset);

	this->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

	this->devcon->OMSetBlendState(this->blendstate, NULL, 0xffffffff);

	D3D11_MAPPED_SUBRESOURCE ms;

	for(unsigned int zIndex = 0; zIndex <= 20; zIndex++) {
		for(unsigned int i = 0; i < Game::MenuManagerPtr->MenuItemPtrs.size(); i++) {

			if(Game::MenuManagerPtr->MenuItemPtrs[i]->showing && zIndex == Game::MenuManagerPtr->MenuItemPtrs[i]->zIndex) {
				this->devcon->Map(this->pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
				memcpy(ms.pData, Game::MenuManagerPtr->MenuItemPtrs[i]->Quad, sizeof(Game::MenuManagerPtr->MenuItemPtrs[i]->Quad));
				this->devcon->Unmap(this->pVBuffer, NULL);
				
				this->devcon->PSSetShaderResources(0, 1, &this->MenuTextures[0].pTexture);
		
				this->devcon->Draw(4, 0);
			}
		}
	}
}

void Graphics::RenderCursor() {
	this->devcon->OMSetRenderTargets(1, &this->backbuffer, NULL);

	this->devcon->VSSetShader(this->pVSMenu, 0, 0);

	UINT stride = sizeof(VERTEX);
	UINT offset = 0;
	this->devcon->IASetVertexBuffers(0, 1, &this->pVBuffer, &stride, &offset);

	this->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

	this->devcon->OMSetBlendState(this->blendstate, NULL, 0xffffffff);

	D3D11_MAPPED_SUBRESOURCE ms;

	this->devcon->Map(this->pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
	memcpy(ms.pData, Game::CursorPtr->Quad, sizeof(Game::CursorPtr->Quad));
	this->devcon->Unmap(this->pVBuffer, NULL);
				
	this->devcon->PSSetShaderResources(0, 1, &Game::CursorPtr->pTexture);
		
	this->devcon->Draw(4, 0);
}

int Graphics::InitPipeline(void) {

	ID3D10Blob *VS, *PS, *VSMenu, *compileErrors;
	string error;
	
	if(FAILED(D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, &compileErrors, 0))) {
		Logger::Log(E_COMPILE_VERTEX_SHADER_FAILED, "Error compiling the vertex shader!", __FILE__, __LINE__, LOG_ERROR);
		error = static_cast<char*>(compileErrors->GetBufferPointer());
		error.pop_back();
		Logger::Log(E_COMPILE_VERTEX_SHADER_FAILED, error, __FILE__, __LINE__, LOG_ERROR);
		return E_PIPELINE_INIT_FAILED;
	}

	if(FAILED(D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "VShaderMenu", "vs_5_0", 0, 0, 0, &VSMenu, &compileErrors, 0))) {
		Logger::Log(E_COMPILE_VERTEX_SHADER_FAILED, "Error compiling the menu vertex shader!", __FILE__, __LINE__, LOG_ERROR);
		error = static_cast<char*>(compileErrors->GetBufferPointer());
		error.pop_back();
		Logger::Log(E_COMPILE_VERTEX_SHADER_FAILED, error, __FILE__, __LINE__, LOG_ERROR);
		return E_PIPELINE_INIT_FAILED;
	}

	if(FAILED(D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS, &compileErrors, 0))) {
		Logger::Log(E_COMPILE_PIXEL_SHADER_FAILED, "Error compiling the pixel shader!", __FILE__, __LINE__, LOG_ERROR);
		error = static_cast<char*>(compileErrors->GetBufferPointer());
		error.pop_back();
		Logger::Log(E_COMPILE_PIXEL_SHADER_FAILED, error, __FILE__, __LINE__, LOG_ERROR);
		return E_PIPELINE_INIT_FAILED;
	}

	if(FAILED(this->dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &this->pVS))){
		Logger::Log(E_CREATE_VERTEX_SHADER_FAILED, "Error creating vertex shader!", __FILE__, __LINE__, LOG_ERROR);
		return E_PIPELINE_INIT_FAILED;
	}

	if(FAILED(this->dev->CreateVertexShader(VSMenu->GetBufferPointer(), VSMenu->GetBufferSize(), NULL, &this->pVSMenu))){
		Logger::Log(E_CREATE_VERTEX_SHADER_FAILED, "Error creating menu vertex shader!", __FILE__, __LINE__, LOG_ERROR);
		return E_PIPELINE_INIT_FAILED;
	}

	if(FAILED(this->dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &this->pPS))) {
		Logger::Log(E_CREATE_PIXEL_SHADER_FAILED, "Error creating pixel shader!", __FILE__, __LINE__, LOG_ERROR);
		return E_PIPELINE_INIT_FAILED;
	}

	// create the input layout object
	D3D11_INPUT_ELEMENT_DESC ied[] = 
	{
		{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0}
	};

	this->dev->CreateInputLayout(ied, 3, VS->GetBufferPointer(), VS->GetBufferSize(), &this->pLayout);
	this->devcon->IASetInputLayout(this->pLayout);

	D3D11_BUFFER_DESC bd;

	SecureZeroMemory(&bd, sizeof(bd));

	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = 64;
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;

	this->dev->CreateBuffer(&bd, NULL, &this->pCBuffer);
	this->devcon->VSSetConstantBuffers(0, 1, &this->pCBuffer);

	return 0;
}

int Graphics::LoadCharacterTexture(string texFile) {
	static int texuid = 0;
	int returnid;
	bool texexists = false;
	texFile = "Textures/" + texFile;
	boost::filesystem::path texFilePath = boost::filesystem::complete(texFile);

	for(unsigned int i = 0; i < this->CharacterTextures.size(); i++) {
		if(this->CharacterTextures[i].texFile == texFile) {
			texexists = true;
			returnid = i;
		}
	}

	if(!texexists) {

		ID3D11ShaderResourceView* pTexture = NULL;

		if(FAILED(D3DX11CreateShaderResourceViewFromFile(this->dev,
														 (TCHAR*)texFilePath.c_str(),
														 NULL,
														 NULL,
														 &pTexture,
														 NULL))) {
			ostringstream message;
			message << "Failed to load texture '" << texFile << "'! Please check if the file exists!";
			Logger::Log(E_GRAPHICS_LOADTEX_FAILED, message.str(), __FILE__, __LINE__, LOG_ERROR);
			return NULL;
		}
		else {
		TEXTURE tex;
		tex.texID = texuid;
		tex.texFile = texFile;
		tex.pTexture = pTexture;
			
		this->CharacterTextures.push_back(tex);

		returnid = texuid;

		texuid++;

		return returnid;
		}
	}
	else {
		return returnid;
	}
}

int Graphics::LoadMenuTexture(string texFile) {
	static int menutexuid = 0;
	int returnid;
	bool texexists = false;
	texFile = "Textures/" + texFile;
	boost::filesystem::path texFilePath = boost::filesystem::complete(texFile);

	for(unsigned int i = 0; i < this->MenuTextures.size(); i++) {
		if(this->MenuTextures[i].texFile == texFile) {
			texexists = true;
			returnid = i;
		}
	}

	if(!texexists) {

		ID3D11ShaderResourceView* pTexture = NULL;

		if(FAILED(D3DX11CreateShaderResourceViewFromFile(this->dev,
														 (TCHAR*)texFilePath.c_str(),
														 NULL,
														 NULL,
														 &pTexture,
														 NULL))) {
			ostringstream message;
			message << "Failed to load MapTile texture '" << texFile << "'! Please check if the file exists!";
			Logger::Log(E_GRAPHICS_LOADTEX_FAILED, message.str(), __FILE__, __LINE__, LOG_ERROR);
			return NULL;
		}
		else {
		TEXTURE tex;
		tex.texID = menutexuid;
		tex.texFile = texFile;
		tex.pTexture = pTexture;
			
		this->MenuTextures.push_back(tex);

		returnid = menutexuid;

		menutexuid++;

		return returnid;
		}
	}
	else {
		return returnid;
	}
}

int Graphics::LoadMapTileTexture(string texFile) {
	static int maptexuid = 0;
	int returnid;
	bool texexists = false;
	texFile = "Textures/MapTiles/" + texFile;
	boost::filesystem::path texFilePath = boost::filesystem::complete(texFile);

	for(unsigned int i = 0; i < this->MapTileTextures.size(); i++) {
		if(this->MapTileTextures[i].texFile == texFile) {
			texexists = true;
			returnid = i;
		}
	}

	if(!texexists) {

		ID3D11ShaderResourceView* pTexture = NULL;

		if(FAILED(D3DX11CreateShaderResourceViewFromFile(this->dev,
														 (TCHAR*)texFilePath.c_str(),
														 NULL,
														 NULL,
														 &pTexture,
														 NULL))) {
			ostringstream message;
			message << "Failed to load texture '" << texFile << "'! Please check if the file exists!";
			Logger::Log(E_GRAPHICS_LOADTEX_FAILED, message.str(), __FILE__, __LINE__, LOG_ERROR);
			return NULL;
		}
		else {
		TEXTURE tex;
		tex.texID = maptexuid;
		tex.texFile = texFile;
		tex.pTexture = pTexture;
			
		this->MapTileTextures.push_back(tex);

		returnid = maptexuid;

		maptexuid++;

		return returnid;
		}
	}
	else {
		return returnid;
	}
}